package org.easystub.dbstub;

import org.hsqldb.jdbc.JDBCDataSource;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public final class DBStub {

    private final DataSource dataSource;
    private final String schema;

    public DBStub() {
        this.schema = "public";
        dataSource = DataSourceFactory.getDataSource();
        reset();
    }

    public DBStub(String schema) {
        this.schema = schema;
        dataSource = DataSourceFactory.getDataSource();
        reset();

        try {
            createSchema(schema);
        } catch(SQLException e) {
            throw new DBStubException(e);
        }
    }

    private void createSchema(String schema) throws SQLException {
        Connection connection = dataSource.getConnection();
        connection.prepareStatement("create schema " + schema).execute();
    }

    public TableBuilder buildTable(String tableName) {
        try {
            return new TableBuilder(tableName, dataSource.getConnection(), schema);
        } catch(SQLException e) {
            throw new DBStubException(e);
        }
    }

    public TableBuilder buildTable(String tableName, PrimaryKey primaryKey) {
        try {
            return new TableBuilder(tableName, dataSource.getConnection(), primaryKey, schema);
        } catch(SQLException e) {
            throw new DBStubException(e);
        }
    }

    public InsertBuilder insertIntoTable(String tableName) {
        try {
            return new InsertBuilder(tableName, dataSource.getConnection(), schema);
        } catch(SQLException e) {
            throw new DBStubException(e);
        }
    }

    private void reset() {
        try {
            dataSource.getConnection().prepareStatement(String.format("drop schema %s cascade", schema)).execute();
        } catch(SQLException e) {
            throw new DBStubException(e);
        }
    }

    public void setupDataFromFixture(Class<? extends Fixture> fixtureClass) {
        try {
            Fixture fixture = fixtureClass.newInstance();
            fixture.setupTest(this);
        } catch(IllegalAccessException e) {
            throw new DBStubException(e);
        } catch(InstantiationException e) {
            throw new DBStubException(e);
        }
    }
}
